#ifndef _ISOCKET_H_
#define _ISOCKET_H_

interface ISockProc : public IBase
{
    std_method(OnSockSend)(crtid cid, crterr err, buf_ptr buf, buf_len size) PURE;
    std_method(OnSockRecv)(crtid cid, crterr err, buf_ptr buf, buf_len size) PURE;
    std_method(OnSockConnect)(crtid cid, crterr err, _sock_t fd) PURE;
    std_method(OnSockEvent)(crtid cid, crtop op, crterr err, _sock_t fd) PURE;
};

// {9C926805-64F5-4728-86A4-AB0208AA1487}
_DEF_IID(IID_ISockProc, 0x9c926805, 0x64f5, 0x4728, 0x86, 0xa4, 0xab, 0x2, 0x8, 0xaa, 0x14, 0x87);

interface ISocket : public IIoDevice
{
    std_method(BindEvent)(IBase* pSocketEvent) PURE;
    std_method(UnBindEvent)() PURE;
    std_method(CreateSock)() PURE;
    std_method(CloseSock)() PURE;
    std_method(IsOpen)() PURE;
    std_method(AttachSock)(_sock_t sock) PURE;
    std_method_(_sock_t, DetachSock)() PURE;
    std_method_(_sock_t, GetSock)() PURE;
    std_method(GetReadOperation)(IID id, IBase** pBase) PURE;
    std_method(GetWriteOperation)(IID id, IBase** pBase) PURE;
};

// {4337751F-F25B-406C-9FB9-7BA540481BB1}
_DEF_IID(IID_ISocket, 0x4337751f, 0xf25b, 0x406c, 0x9f, 0xb9, 0x7b, 0xa5, 0x40, 0x48, 0x1b, 0xb1);

// {DF3C532D-50A8-4FD3-B7E0-6EFFCD08A54A}
_DEF_IID(IID_IReadOperation, 0xdf3c532d, 0x50a8, 0x4fd3, 0xb7, 0xe0, 0x6e, 0xff, 0xcd, 0x8, 0xa5, 0x4a);

// {9E97F4A9-2423-4E14-B982-FF4575674CDC}
_DEF_IID(IID_IWriteOperation, 0x9e97f4a9, 0x2423, 0x4e14, 0xb9, 0x82, 0xff, 0x45, 0x75, 0x67, 0x4c, 0xdc);

#define TCP_READIO  0x10
#define TCP_WRITEIO 0x20

interface ITcpSocket : public ISocket
{
    std_method(ReadIo)(ULONG pos, ULONG size, crtid event, int tm) PURE;
    std_method(WriteIo)(ULONG pos, ULONG size, crtid event, int tm) PURE;
    std_method(ConnectIo)(NET_ADDR addr, NET_PORT port, crtid op, int tm) PURE;
};

// {37ACA045-F4F5-4481-93F9-B260EA1A1305}
_DEF_IID(IID_ITcpSocket, 0x37aca045, 0xf4f5, 0x4481, 0x93, 0xf9, 0xb2, 0x60, 0xea, 0x1a, 0x13, 0x5);

#define SSL_BASE 1000

/*
TLS1.3 message types. Defined:
https://tools.ietf.org/html/rfc8446#appendix-B.3
*/

#define TLS_SSL_CLIENT_HELLO SSL_BASE + 1

#define TLS_SSL_SERVER_HELLO        SSL_BASE + 2
#define TLS_SSL_SERVER_CERTIFICATE  SSL_BASE + 3
#define TLS_SSL_SERVER_KEY_EXCHANGE SSL_BASE + 4

#define TLS_SSL_CERTIFICATE_REQUEST              SSL_BASE + 5
#define TLS_SSL_SERVER_HELLO_DONE                SSL_BASE + 6
#define TLS_SSL_CLIENT_CERTIFICATE               SSL_BASE + 7
#define TLS_SSL_CLIENT_KEY_EXCHANGE              SSL_BASE + 8
#define TLS_SSL_CERTIFICATE_VERIFY               SSL_BASE + 9
#define TLS_SSL_CLIENT_CHANGE_CIPHER_SPEC        SSL_BASE + 10
#define TLS_SSL_CLIENT_FINISHED                  SSL_BASE + 11
#define TLS_SSL_SERVER_CHANGE_CIPHER_SPEC        SSL_BASE + 12
#define TLS_SSL_SERVER_FINISHED                  SSL_BASE + 13
#define TLS_SSL_FLUSH_BUFFERS                    SSL_BASE + 14
#define TLS_SSL_HANDSHAKE_WRAPUP                 SSL_BASE + 15
#define TLS_SSL_HANDSHAKE_OVER                   SSL_BASE + 16
#define TLS_SSL_SERVER_NEW_SESSION_TICKET        SSL_BASE + 17
#define TLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT SSL_BASE + 18

interface ITcpSocketSsl : public ITcpSocket
{
    std_method(LoadCertificate)(UCHAR* buf, size_t size) PURE;
    std_method(SetSSLCtxAddress)(LPCSTR hostname) PURE;
};

// {861BBC5D-A0CC-496F-9E54-3F972FB4943E}
_DEF_IID(IID_ITcpSocketSsl, 0x861bbc5d, 0xa0cc, 0x496f, 0x9e, 0x54, 0x3f, 0x97, 0x2f, 0xb4, 0x94, 0x3e);

interface IUdpSocket : public ISocket
{
    std_method(ReadIo)(NET_ADDR addr, NET_PORT port, IBase* pBase, crtid cid) PURE;
    std_method(WriteIo)(NET_ADDR addr, NET_PORT port, IBase* pBase, crtid cid) PURE;
};

// {7DB4FEA2-E7E2-4C1D-A5D6-751CA0CA07EA}
_DEF_IID(IID_IUdpSocket, 0x7db4fea2, 0xe7e2, 0x4c1d, 0xa5, 0xd6, 0x75, 0x1c, 0xa0, 0xca, 0x7, 0xea);

#define LISTEN_OPEN  0
#define LISTEN_CLOSE 1

interface IListen : public ISocket
{
    std_method(Listen)(NET_ADDR addr, NET_PORT port) PURE;
    std_method(Listen6)(NET_ADDR addr, NET_PORT port) PURE;
    std_method(Accept)(int on) PURE;
};

// {BB9DA617-80BE-4E04-8EB4-13CF43F1EBD1}
_DEF_IID(IID_IListen, 0xbb9da617, 0x80be, 0x4e04, 0x8e, 0xb4, 0x13, 0xcf, 0x43, 0xf1, 0xeb, 0xd1);

interface IAcceptListen : public IBase
{
    std_method(Accept)(_sock_t s, SOCKADDR_PTR sa, socklen_t sl, crterr err) PURE;
};

// {8221E95A-6E9F-4ADF-8F75-811BBC6DFBD0}
_DEF_IID(IID_IAcceptListen, 0x8221e95a, 0x6e9f, 0x4adf, 0x8f, 0x75, 0x81, 0x1b, 0xbc, 0x6d, 0xfb, 0xd0);

interface ITcpListen : public IListen
{
    std_method(BindAccept)(IBase* pAccept) PURE;
    std_method(UnBindAccpet)() PURE;
};

// {829C3A23-4D1C-420A-BFAD-646A1924AA15}
_DEF_IID(IID_ITcpListen, 0x829c3a23, 0x4d1c, 0x420a, 0xbf, 0xad, 0x64, 0x6a, 0x19, 0x24, 0xaa, 0x15);

interface ITcpSslListen : public ITcpListen
{
};

// {829C3A23-4D1C-420A-BFAD-646A1924AA16}
_DEF_IID(IID_ITcpSslListen, 0x829c3a23, 0x4d1c, 0x420a, 0xbf, 0xad, 0x64, 0x6a, 0x19, 0x24, 0xaa, 0x16);

#endif
